using System;
using System.Collections;
using System.Text;

using Qiang.Topology.Operation;

namespace Qiang.Topology.Geometries
{
    /// <summary>  
    /// Models a collection of <c>Point</c>s.
    /// </summary>
    public class MultiPoint : GeometryCollection,IMultiPoint
    {
        /// <summary>
        /// Represents an empty <c>MultiPoint</c>.
        /// </summary>
        public static new readonly IMultiPoint Empty = new GeometryFactory().CreateMultiPoint(new Point[] { });

        /// <summary>
        /// Constructs a <c>MultiPoint</c>.
        /// </summary>
        /// <param name="points">
        /// The <c>Point</c>s for this <c>MultiPoint</c>
        /// , or <c>null</c> or an empty array to create the empty point.
        /// Elements may be empty <c>Point</c>s, but not <c>null</c>s.
        /// </param>
        /// <param name="precisionModel">
        /// The specification of the grid of allowable points
        /// for this <c>MultiPoint</c>.
        /// </param>
        /// <param name="SRID">
        /// The ID of the Spatial Reference System used by this
        /// <c>MultiPoint</c>.
        /// </param>
        /// <deprecated>
        /// Use GeometryFactory instead.
        /// </deprecated>
        [Obsolete("Use GeometryFactory instead")]
        public MultiPoint(Point[] points, PrecisionModel precisionModel, int SRID) 
            : base(points, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.Instance)) { }

        /// <param name="points">
        /// The <c>Point</c>s for this <c>MultiPoint</c>
        /// , or <c>null</c> or an empty array to create the empty point.
        /// Elements may be empty <c>Point</c>s, but not <c>null</c>s.
        /// </param>
        public MultiPoint(IPoint[] points, GeometryFactory factory) : base(points, factory) { }


        public MultiPoint(IPoint[] points)
            : this(points, DefaultGeometryFactory)
        { }


        public override Dimensions Dimension 
        {
            get
            {
                return Dimensions.Point;
            }
        }

        public override Dimensions BoundaryDimension
        {
            get
            {
                return Dimensions.False;
            }
        }

        [Obsolete("Use reflection! GetType().FullName")]
        public override string GeometryType
        {
            get
            {
                return "MultiPoint";
            }
        }

        public override IGeometry Boundary
        {
            get
            {
                return Factory.CreateGeometryCollection(null);
            }
        }

        public override bool IsSimple
        {
            get
            {
                return (new IsSimpleOp()).IsSimple((MultiPoint)ToInternalGeometry(this));
            }
        }

        public override bool IsValid
        {
            get
            {
                return true;
            }
        }

        public override bool EqualsExact(IGeometry other, double tolerance) 
        {
            if (!IsEquivalentClass(other)) 
                return false;            
            return base.EqualsExact(other, tolerance);
        }

        /// <summary>
        /// Returns the <c>Coordinate</c> at the given position.
        /// </summary>
        /// <param name="n">
        /// The index of the <c>Coordinate</c> to retrieve, beginning
        /// at 0.
        /// </param>
        /// <returns>
        /// The <c>n</c>th <c>Coordinate</c>.
        /// </returns>
        protected virtual Coordinate GetCoordinate(int n) 
        {
            return ((Point)geometries[n]).Coordinate;
        }
    }
}
